#include <iostream>
#include <stdio.h>

/*
 * 多继承有函数覆盖的特点
 */

class Base1
{
	public:
		virtual void function_1()
		{
			printf("Base1 function_1...\n");
		}

		virtual void function_2()
		{
			printf("Base1 function_2...\n");
		}
	
};

class Base2
{
	public:
		virtual void function_3()
		{
			printf("Base2 function_3...\n");
		}

		virtual void function_4()
		{
			printf("Base2 function_4...\n");
		}
	
};


class Sub :  Base1,  Base2
{
	public:
		virtual void function_1()
		{
			printf("Sub function_1...\n");
		}

		virtual void function_3()
		{
			printf("Sub function_3...\n");
		}

		virtual void function_5()
		{
			printf("Sub function_5...\n");
		}
};

int main(int argc, char ** argv)
{
	Sub sub;

	printf("size = %d\n", sizeof(class Sub));	// 8。 直接继承两个父类，所以有两个虚函数表

	printf("sub address is %x.\n", &sub);		// this 指针，是堆栈里面的地址。虚表的地址不是this指针，是this指针的前四个字节。

	/* 对象的前4字节是第一个Base1的虚表 */
	printf("sub virtual table address is:%x\n", *(int*)&sub);   		

	typedef void(*pfunction)(void);
	
	pfunction pf;

	for (int i = 0; i < 4; i++) {
		int temp = *((int*)(*(int*)&sub) + i);	
		if (temp == 0) {
			break;
		}

		pf = (pfunction)temp;
		pf();
	}

	/* 对象的第二个4字节是Base2的虚表 */
	printf("sub virtual table address is:%x\n", *(int*)((int)&sub+4));  
	pfunction pf2;

	for (int k = 0; k < 2; k++) {
		int temp = *((int*)(*(int*)((int)&sub+4)) + k);
		pf2 = (pfunction)temp;
		pf2();
	}

	return 0;
}

/*
Sub function_1
Base1 function_2
Sub function_5

Sub address
Sub function_3
Base2 function_4
 */
/*
size = 8
sub address is bfb0aa90.
sub virtual table address is:8048a68
Sub function_1...
Base1 function_2...
Sub function_3...
Sub function_5...
sub virtual table address is:8048a80
Sub function_3...
Base2 function_4...
*/
#if 0

1.覆盖的是哪个在哪个虚表里；

int main(int argc, char ** argv)
{
 80486b0:	55                   	push   %ebp
 80486b1:	89 e5                	mov    %esp,%ebp
 80486b3:	83 e4 f0             	and    $0xfffffff0,%esp
 80486b6:	83 ec 30             	sub    $0x30,%esp
	Sub sub;
 80486b9:	8d 44 24 10          	lea    0x10(%esp),%eax
 80486bd:	89 04 24             	mov    %eax,(%esp)
 80486c0:	e8 ef 01 00 00       	call   80488b4 <_ZN3SubC1Ev>

	printf("size = %d\n", sizeof(class Sub));	// 8。 直接继承两个父类，所以有两个虚函数表
 80486c5:	c7 44 24 04 08 00 00 	movl   $0x8,0x4(%esp)
 80486cc:	00 
 80486cd:	c7 04 24 12 8a 04 08 	movl   $0x8048a12,(%esp)
 80486d4:	e8 a7 fe ff ff       	call   8048580 <printf@plt>

	printf("sub address is %x.\n", &sub);		// this 指针，是堆栈里面的地址。虚表的地址不是this指针，是this指针的前四个字节。
 80486d9:	8d 44 24 10          	lea    0x10(%esp),%eax
 80486dd:	89 44 24 04          	mov    %eax,0x4(%esp)
 80486e1:	c7 04 24 1d 8a 04 08 	movl   $0x8048a1d,(%esp)
 80486e8:	e8 93 fe ff ff       	call   8048580 <printf@plt>

	/* 对象的前4字节是第一个Base1的虚表 */
	printf("sub virtual table address is:%x\n", *(int*)&sub);   		
 80486ed:	8d 44 24 10          	lea    0x10(%esp),%eax
 80486f1:	8b 00                	mov    (%eax),%eax
 80486f3:	89 44 24 04          	mov    %eax,0x4(%esp)
 80486f7:	c7 04 24 34 8a 04 08 	movl   $0x8048a34,(%esp)
 80486fe:	e8 7d fe ff ff       	call   8048580 <printf@plt>

	typedef void(*pfunction)(void);
	
	pfunction pf;

	for (int i = 0; i < 4; i++) {
 8048703:	c7 44 24 2c 00 00 00 	movl   $0x0,0x2c(%esp)
 804870a:	00 
 804870b:	eb 35                	jmp    8048742 <main+0x92>
		int temp = *((int*)(*(int*)&sub) + i);	
 804870d:	8b 44 24 2c          	mov    0x2c(%esp),%eax
 8048711:	8d 14 85 00 00 00 00 	lea    0x0(,%eax,4),%edx
 8048718:	8d 44 24 10          	lea    0x10(%esp),%eax
 804871c:	8b 00                	mov    (%eax),%eax
 804871e:	01 d0                	add    %edx,%eax
 8048720:	8b 00                	mov    (%eax),%eax
 8048722:	89 44 24 24          	mov    %eax,0x24(%esp)
		if (temp == 0) {
 8048726:	83 7c 24 24 00       	cmpl   $0x0,0x24(%esp)
 804872b:	75 02                	jne    804872f <main+0x7f>
			break;
 804872d:	eb 1a                	jmp    8048749 <main+0x99>
		}

		pf = (pfunction)temp;
 804872f:	8b 44 24 24          	mov    0x24(%esp),%eax
 8048733:	89 44 24 20          	mov    %eax,0x20(%esp)
		pf();
 8048737:	8b 44 24 20          	mov    0x20(%esp),%eax
 804873b:	ff d0                	call   *%eax

	typedef void(*pfunction)(void);
	
	pfunction pf;

	for (int i = 0; i < 4; i++) {
 804873d:	83 44 24 2c 01       	addl   $0x1,0x2c(%esp)
 8048742:	83 7c 24 2c 03       	cmpl   $0x3,0x2c(%esp)
 8048747:	7e c4                	jle    804870d <main+0x5d>
		pf = (pfunction)temp;
		pf();
	}

	/* 对象的第二个4字节是Base2的虚表 */
	printf("sub virtual table address is:%x\n", *(int*)((int)&sub+4));  
 8048749:	8d 44 24 10          	lea    0x10(%esp),%eax
 804874d:	83 c0 04             	add    $0x4,%eax
 8048750:	8b 00                	mov    (%eax),%eax
 8048752:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048756:	c7 04 24 34 8a 04 08 	movl   $0x8048a34,(%esp)
 804875d:	e8 1e fe ff ff       	call   8048580 <printf@plt>
	pfunction pf2;

	for (int k = 0; k < 2; k++) {
 8048762:	c7 44 24 28 00 00 00 	movl   $0x0,0x28(%esp)
 8048769:	00 
 804876a:	eb 2f                	jmp    804879b <main+0xeb>
		int temp = *((int*)(*(int*)((int)&sub+4)) + k);
 804876c:	8b 44 24 28          	mov    0x28(%esp),%eax
 8048770:	8d 14 85 00 00 00 00 	lea    0x0(,%eax,4),%edx
 8048777:	8d 44 24 10          	lea    0x10(%esp),%eax
 804877b:	83 c0 04             	add    $0x4,%eax
 804877e:	8b 00                	mov    (%eax),%eax
 8048780:	01 d0                	add    %edx,%eax
 8048782:	8b 00                	mov    (%eax),%eax
 8048784:	89 44 24 1c          	mov    %eax,0x1c(%esp)
		pf2 = (pfunction)temp;
 8048788:	8b 44 24 1c          	mov    0x1c(%esp),%eax
 804878c:	89 44 24 18          	mov    %eax,0x18(%esp)
		pf2();
 8048790:	8b 44 24 18          	mov    0x18(%esp),%eax
 8048794:	ff d0                	call   *%eax

	/* 对象的第二个4字节是Base2的虚表 */
	printf("sub virtual table address is:%x\n", *(int*)((int)&sub+4));  
	pfunction pf2;

	for (int k = 0; k < 2; k++) {
 8048796:	83 44 24 28 01       	addl   $0x1,0x28(%esp)
 804879b:	83 7c 24 28 01       	cmpl   $0x1,0x28(%esp)
 80487a0:	7e ca                	jle    804876c <main+0xbc>
		int temp = *((int*)(*(int*)((int)&sub+4)) + k);
		pf2 = (pfunction)temp;
		pf2();
	}

	return 0;
 80487a2:	b8 00 00 00 00       	mov    $0x0,%eax
}
 80487a7:	c9                   	leave  
 80487a8:	c3                   	ret

#endif
